package com.qiangesoft.blog.file.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qiangesoft.blog.file.config.FileStoreConfig;
import com.qiangesoft.blog.file.core.FileStoreStrategy;
import com.qiangesoft.blog.file.core.FileStoreStrategyContext;
import com.qiangesoft.blog.file.entity.SysFileInfo;
import com.qiangesoft.blog.file.enums.FileStoreTypeEnum;
import com.qiangesoft.blog.file.mapper.SysFileInfoMapper;
import com.qiangesoft.blog.file.model.FileInfoVo;
import com.qiangesoft.blog.file.service.ISysFileInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * 文件存储信息Service业务层处理
 *
 * @author qiange
 * @date 2023-04-26
 */
@Service
public class SysFileInfoServiceImpl extends ServiceImpl<SysFileInfoMapper, SysFileInfo> implements ISysFileInfoService {

    @Autowired
    private FileStoreConfig fileStoreConfig;
    @Autowired
    private SysFileInfoMapper sysFileInfoMapper;
    @Autowired
    private FileStoreStrategyContext fileStoreStrategyContext;

    @Override
    public FileInfoVo uploadFile(MultipartFile file) throws Exception {
        FileStoreStrategy fileStoreStrategy = fileStoreStrategyContext.getStrategy(fileStoreConfig.getType());
        FileInfoVo fileInfoVo = fileStoreStrategy.uploadFile(file);

        saveFileInfo(fileInfoVo);
        fileInfoVo.setStoreUrl(fileStoreConfig.getNginxHost() + fileInfoVo.getStoreUrl());
        return fileInfoVo;
    }

    /**
     * 保存文件记录
     *
     * @param fileInfoVo
     */
    private void saveFileInfo(FileInfoVo fileInfoVo) {
        SysFileInfo sysFileInfo = new SysFileInfo();
        sysFileInfo.setFileName(fileInfoVo.getFileName());
        sysFileInfo.setOriginalFileName(fileInfoVo.getOriginalFileName());
        sysFileInfo.setStoreType(fileInfoVo.getStoreType());
        sysFileInfo.setStoreUrl(fileInfoVo.getStoreUrl());
        sysFileInfo.setFileExtension(fileInfoVo.getFileExtension());
        sysFileInfo.setFileSize(fileInfoVo.getFileSize());
        sysFileInfo.setCategory(fileInfoVo.getCategory());
        sysFileInfo.setExpireFlag(false);
        baseMapper.insert(sysFileInfo);

        fileInfoVo.setFileId(sysFileInfo.getId());
        fileInfoVo.setExpireFlag(sysFileInfo.getExpireFlag());
    }

    @Override
    public FileInfoVo uploadFileByPath(MultipartFile file, String path) throws Exception {
        FileStoreStrategy fileStoreStrategy = fileStoreStrategyContext.getStrategy(fileStoreConfig.getType());
        FileInfoVo fileInfoVo = fileStoreStrategy.uploadFile(file, path);

        saveFileInfo(fileInfoVo);
        fileInfoVo.setStoreUrl(fileStoreConfig.getNginxHost() + fileInfoVo.getStoreUrl());
        return fileInfoVo;
    }

    @Override
    public FileInfoVo uploadFile(InputStream inputStream, String contentType) throws Exception {
        FileStoreStrategy fileStoreStrategy = fileStoreStrategyContext.getStrategy(fileStoreConfig.getType());
        FileInfoVo fileInfoVo = fileStoreStrategy.uploadFile(inputStream, contentType);

        saveFileInfo(fileInfoVo);
        fileInfoVo.setStoreUrl(fileStoreConfig.getNginxHost() + fileInfoVo.getStoreUrl());
        return fileInfoVo;
    }

    @Override
    public FileInfoVo uploadFileByPath(InputStream inputStream, String contentType, String path) throws Exception {
        FileStoreStrategy fileStoreStrategy = fileStoreStrategyContext.getStrategy(fileStoreConfig.getType());
        FileInfoVo fileInfoVo = fileStoreStrategy.uploadFile(inputStream, contentType, path);

        saveFileInfo(fileInfoVo);
        fileInfoVo.setStoreUrl(fileStoreConfig.getNginxHost() + fileInfoVo.getStoreUrl());
        return fileInfoVo;
    }

    @Override
    public List<FileInfoVo> batchUploadFile(MultipartFile[] files) throws Exception {
        FileStoreStrategy fileStoreStrategy = fileStoreStrategyContext.getStrategy(fileStoreConfig.getType());
        List<FileInfoVo> fileInfoVos = fileStoreStrategy.batchUploadFile(files);

        for (FileInfoVo fileInfoVo : fileInfoVos) {
            saveFileInfo(fileInfoVo);
            fileInfoVo.setStoreUrl(fileStoreConfig.getNginxHost() + fileInfoVo.getStoreUrl());
        }

        return fileInfoVos;
    }

    @Override
    public void download(Long fileId, HttpServletRequest request, HttpServletResponse response) throws Exception {
        SysFileInfo sysFileInfo = baseMapper.selectById(fileId);
        String storeType = sysFileInfo.getStoreType();
        FileStoreTypeEnum typeEnum = FileStoreTypeEnum.getEnumByCode(storeType);

        FileStoreStrategy fileStoreStrategy = fileStoreStrategyContext.getStrategy(typeEnum);
        if (FileStoreTypeEnum.FILE_LOCAL.equals(typeEnum)) {
            fileStoreStrategy.downloadFile(sysFileInfo.getStoreUrl(), request, response);
        } else {
            fileStoreStrategy.downloadFile(sysFileInfo.getFileName(), request, response);
        }
    }

    @Override
    public FileInfoVo getFileInfoById(Long fileId) {
        SysFileInfo sysFileInfo = baseMapper.selectById(fileId);
        sysFileInfo.setStoreUrl(fileStoreConfig.getNginxHost() + sysFileInfo.getStoreUrl());
        return FileInfoVo.fromEntity(sysFileInfo);
    }

    @Override
    public List<FileInfoVo> getFileInfoByIds(List<Long> fileIds) {
        List<SysFileInfo> sysFileInfos = baseMapper.selectBatchIds(fileIds);

        List<FileInfoVo> fileInfoVos = new ArrayList<>();
        for (SysFileInfo sysFileInfo : sysFileInfos) {
            FileInfoVo fileInfoVo = FileInfoVo.fromEntity(sysFileInfo);
            fileInfoVo.setStoreUrl(fileStoreConfig.getNginxHost() + sysFileInfo.getStoreUrl());
            fileInfoVos.add(fileInfoVo);
        }
        return fileInfoVos;
    }
}
